<template>
  <div class="cjui-wfrow-container" :style="`--cjui-wfcol-width: ${widthPer}`">
    <div ref="wfrowRef" class="cjui-wfrow-body" :id="wfrowId">
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts">
export default {
  name: 'CjuiWaterFallRow',
}
</script>

<script lang="ts" setup>
import { onMounted, onBeforeUnmount, ref, watch, nextTick } from 'vue';
import { randomWord } from '@/utils/basic/string';

function getArrayMinIndex(arr: number[] = []) {
  const min = Math.min.apply(null, arr);
  const index = arr.findIndex((el) => el === min);
  return index;
}
function getArrayMax(arr: number[] = []) {
  return Math.max.apply(null, arr);
}

interface Props {
  count?: number // 默认列数
  xs?: number // < 768px 时的列数
  sm?: number // < 992px 时的列数
  md?: number // < 1200px 时的列数
  lg?: number // < 1920px 时的列数
  xl?: number // >= 1920px 时的列数
}
const props = withDefaults(defineProps<Props>(), {
  count: 1,
  xs: -1,
  sm: -1,
  md: -1,
  lg: -1,
  xl: -1
});
defineExpose({ renderAll, renderNew });

const wfrowRef = ref();
const time = new Date();
const wfrowId = 'id' + randomWord() + time.getTime();
const widthPer = ref('100%');

let wfrowWidth = 0;

let column = 1;
function setColumn() {
  column = props.count > 0 ? props.count : 1;
  if (wfrowWidth < 768 && props.xs > 0) column = props.xs;
  if (wfrowWidth >= 768 && props.sm > 0) column = props.sm;
  if (wfrowWidth >= 992 && props.md > 0) column = props.md;
  if (wfrowWidth >= 1200 && props.lg > 0) column = props.lg;
  if (wfrowWidth >= 1920 && props.xl > 0) column = props.xl;
  
  widthPer.value = 100 / column + '%';
}

let heightList: number[] = [];
function setHeightList() {
  let array = [];
  for (let i = 0; i < column; i++) {
    array.push(0);
  }
  heightList = array;
}

let timer: any = null;
function imgLoadEvent() {
  clearTimeout(timer)
  timer = setTimeout(() =>{
    timer = null;
    renderAll();
  }, 200);
}

let minIndex = 0;
let max = 0;
let nodeNumber = 0;
function renderAll() {
  // console.log('renderAll')
  const wfColNodes: any = document.querySelectorAll(`#${wfrowId} > .cjui-wfcol-container`);
  for (let i=0; i<wfColNodes.length; i++) {
    const imgNodes = wfColNodes[i].querySelectorAll('img');
    for (const imgNode of imgNodes) {
      const img = new Image();
      img.src = imgNode.getAttribute('src');
      if (!img.complete) {
        img.onload = imgLoadEvent;
        img.onerror = imgLoadEvent;
      }
    }

    minIndex = getArrayMinIndex(heightList);
    wfColNodes[i].style.setProperty('left', ((minIndex % column) * 100) / column + "%");
    wfColNodes[i].style.setProperty('top', heightList[minIndex] + 'px');
    wfColNodes[i].style.setProperty('opacity', 1);

    heightList[minIndex] += wfColNodes[i].offsetHeight;
    // console.log('heightList', wfColNodes[i].offsetHeight, wfColNodes[i])

    max = getArrayMax(heightList);
    wfrowRef.value.style.height = max + 'px';
  }
  nodeNumber = wfColNodes.length;
}

let timerNew: any = null;
function imgLoadEventNew() {
  clearTimeout(timerNew)
  timerNew = setTimeout(() =>{
    timerNew = null;
    renderNewMethod();
  }, 200);
}

// 追加新元素时的渲染方法
let oldHeightList: number[] = [];
let oldNodeNumber = 0;
function renderNewMethod() {
  heightList = [...oldHeightList];

  const wfColNodes: any = document.querySelectorAll(`#${wfrowId} > .cjui-wfcol-container`);
  for (let i=oldNodeNumber; i<wfColNodes.length; i++) {
    const imgNodes = wfColNodes[i].querySelectorAll('img');
    for (const imgNode of imgNodes) {
      const img = new Image();
      img.src = imgNode.getAttribute('src');
      if (!img.complete) {
        img.onload = imgLoadEventNew;
        img.onerror = imgLoadEventNew;
      }
    }

    minIndex = getArrayMinIndex(heightList);
    wfColNodes[i].style.setProperty('left', ((minIndex % column) * 100) / column + "%");
    wfColNodes[i].style.setProperty('top', heightList[minIndex] + 'px');
    wfColNodes[i].style.setProperty('opacity', 1);

    heightList[minIndex] += wfColNodes[i].offsetHeight;

    max = getArrayMax(heightList);
    wfrowRef.value.style.height = max + 'px';
  }
  nodeNumber = wfColNodes.length;
}
function renderNew() {
  oldHeightList = heightList;
  oldNodeNumber = nodeNumber;
  nextTick(() => {
    renderNewMethod();
  });
}

watch(() => [props.count, props.xs, props.sm, props.md, props.lg, props.xl], () => {
  const oldColumn = column;
  setColumn();
  if (column !== oldColumn) {
    nextTick(() => {
      setHeightList();
      renderAll();
    });
  }
}, {
  immediate: false,
});

const ro = new ResizeObserver(_entries => {
  const wfrowWidthNew = wfrowRef.value.offsetWidth;
  if (wfrowWidth !== wfrowWidthNew) {
    wfrowWidth = wfrowWidthNew;
    setColumn();
    nextTick(() => {
      setHeightList();
      renderAll();
    });
  }
})

onMounted(() => {
  ro.observe(wfrowRef.value)
});

onBeforeUnmount(() => {
  ro.disconnect()
});
</script>

<style>
.cjui-wfrow-container {
  width: 100%;
  position: relative;
  margin-right: -8px;
}

.cjui-wfrow-body {
  position: relative;
  margin-left: -8px;
  margin-right: -8px;
  overflow: hidden;
  transition: height ease 0.1s;
}
</style>